package com.sugo.seckill.order.service.impl;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import com.github.pagehelper.Page;
import com.sugo.seckill.aop.Servicelock;
import com.sugo.seckill.http.HttpResult;
import com.sugo.seckill.http.HttpStatus;
import com.sugo.seckill.mapper.order.SeckillGoodsMapper;
import com.sugo.seckill.mapper.order.SeckillOrderMapper;
import com.sugo.seckill.mapper.pay.TbPayLogMapper;
import com.sugo.seckill.order.service.SeckillOrderService;
import com.sugo.seckill.page.PageResult;
import com.sugo.seckill.pojo.*;
import com.sugo.seckill.queue.jvm.SeckillQueue;
import com.sugo.seckill.utils.IdWorker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import com.github.pagehelper.PageHelper;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

/**
 * 服务实现层
 * @author Administrator
 *
 */
@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

	@Autowired
	private SeckillOrderMapper seckillOrderMapper;

	//注入支付
	@Autowired
	private TbPayLogMapper payLogMapper;


	//注入商品对象
	@Autowired
	private SeckillGoodsMapper seckillGoodsMapper;

	//注入redis
	@Autowired
	private RedisTemplate redisTemplate;

	//注入Idworker
	@Autowired
	private IdWorker idWorker;

	//@Autowired
	//private RocketMQSender mqSender;


	//程序锁
	//互斥锁 参数默认false，不公平锁
	private Lock lock = new ReentrantLock(true);

	//日志
	private final static Logger LOGGER = LoggerFactory.getLogger(SeckillOrderServiceImpl.class);

	//获取当前可用的cpu核心数
	private static int corePoolSize = Runtime.getRuntime().availableProcessors();

	//创建线程池  调整队列数 拒绝服务
	private static ThreadPoolExecutor executor  = new ThreadPoolExecutor(corePoolSize, corePoolSize+1, 10l, TimeUnit.SECONDS,
			new LinkedBlockingQueue<>(1000));

	// disruptor 队列 --- 600w /s
	// 分布式队列
	// redis
	// mq


	public void getSeckillGoods(Long seckillId){

		redisTemplate.delete("seckill_goods_"+seckillId);
		redisTemplate.delete("seckill_goods_stock_"+seckillId);

		//创建example对象
		Example example = new Example(TbSeckillGoods.class);
		Example.Criteria criteria = example.createCriteria();

		//设置查询条件
		//状态可用
		criteria.andEqualTo("status",1);
		//时间必须在活动区间
		criteria.andCondition("now() BETWEEN start_time_date AND end_time_date");
		//库存必须大于0
		criteria.andGreaterThan("stockCount",0);

		//获取Redis中所有的key,实现排除当前Redis中已经存在的商品
		Set<Long> ids = redisTemplate.boundHashOps("seckillGoods").keys();
		//判断
		if(ids!=null && ids.size()>0){
			criteria.andNotIn("id",ids);
		}

		//查询
		List<TbSeckillGoods> seckillGoodsList = seckillGoodsMapper.selectByExample(example);

		//判断是否有入库商品
		if(seckillGoodsList!=null && seckillGoodsList.size()>0){
			//循环
			for (TbSeckillGoods goods : seckillGoodsList) {

				//放入商品对象
				redisTemplate.opsForValue().set("seckill_goods_"+goods.getId(),goods);
				//存储库存
				redisTemplate.opsForValue().set("seckill_goods_stock_"+goods.getId(),goods.getStockCount());

               /* //存储到redis
                redisTemplate.boundHashOps("seckillGoods").put(String.valueOf(goods.getId()),goods);
                //存储库存:剩余库存存，用来防止超卖
                redisTemplate.boundHashOps("seckillGoodsCount").put(String.valueOf(goods.getId()),goods.getStockCount());*/

			}
		}
	}



	/**
	 * 按分页查询
	 */
	@Override
	@Transactional
	public PageResult findPage(int pageNum, int pageSize) {
		PageHelper.startPage(pageNum, pageSize);
		Page<TbSeckillOrder> page=   (Page<TbSeckillOrder>) seckillOrderMapper.selectByExample(null);
		return new PageResult(page.getTotal(), page.getResult());
	}


	/**
	 * 根据ID获取实体
	 * @param id
	 * @return
	 */
	@Override
	@Transactional
	public TbSeckillOrder findOne(Long id){
		return seckillOrderMapper.selectByPrimaryKey(id);
	}

	/**
	 * @Description: 方式1-1：普通的下单方式,会出现库存超卖的问题
	 * @Author: hubin
	 * @CreateDate: 2020/6/10 10:54
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/6/10 10:54
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrder(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {
			LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
			//从数据库中查询商品信息
			TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillId);
			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
				if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
				System.out.println(seckillGoods.getStartTimeDate() + "==" + new Date());
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");


			}

			if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){

				LOGGER.info("活动结束时间 {}",seckillGoods.getEndTimeDate().getTime());
				LOGGER.info("现在时刻 {}",new Date().getTime());


				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}

			LOGGER.info("开始扣减库存 订单ID {}",seckillId);
			//扣减库存
			seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
			//销量加1
			seckillGoods.setSales(seckillGoods.getSales()+1);
			//更新秒杀信息
			seckillGoodsMapper.updateByPrimaryKey(seckillGoods);

			LOGGER.info("开始下单");

			//保存（redis）订单
			System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
			TbSeckillOrder seckillOrder=new TbSeckillOrder();
			seckillOrder.setId(orderId);
			seckillOrder.setCreateTime(new Date());
			//秒杀价格
			seckillOrder.setMoney(seckillGoods.getPrice());
			seckillOrder.setSeckillId(seckillId);
			//状态
			seckillOrder.setStatus("0");

			//保存订单
			seckillOrderMapper.insertSelective(seckillOrder);


		} catch (RuntimeException e) {
			e.printStackTrace();
		}
		return HttpResult.ok(orderId+"");
	}


	/**
	 * @Description: 方式1-2：普通的下单方式,会出现库存超卖的问题
	 * @Author: hubin
	 * @CreateDate: 2020/6/10 10:54
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/6/10 10:54
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrderMultiThread(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {
			//从数据库中查询商品信息
			//TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillId);

			//商品数据可以从缓存中获取
			TbSeckillGoods seckillGoods = (TbSeckillGoods) redisTemplate.opsForValue().get("seckill_goods_" + seckillId);


			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus() ){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
			if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime()>new Date().getTime()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");
			}
			if(seckillGoods.getEndTimeDate().getTime()<= new Date().getTime() ){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}
			//扣减库存
			seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
			//销量加1
			seckillGoods.setSales(seckillGoods.getSales()+1);
			//更新秒杀信息
			seckillGoodsMapper.updateByPrimaryKey(seckillGoods);

			Runnable task = () -> {
				//保存（redis）订单
				System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
				TbSeckillOrder seckillOrder=new TbSeckillOrder();
				seckillOrder.setId(orderId);
				seckillOrder.setCreateTime(new Date());
				seckillOrder.setMoney(seckillGoods.getCostPrice());//秒杀价格
				seckillOrder.setSeckillId(seckillId);
				seckillOrder.setStatus("0");//状态

				//保存订单
				seckillOrderMapper.insertSelective(seckillOrder);

			};
			//执行
			executor.execute(task);

		} catch (RuntimeException e) {
			e.printStackTrace();
		}
		return HttpResult.ok(orderId+"");
	}

	/**
	 * @Description: 3-1 使用aop锁实现库存超卖控制
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Servicelock
	@Override
	public HttpResult startSubmitOrderByAOPLock(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {
			LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
			//从数据库中查询商品信息
			//TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillId);

			//商品数据可以从缓存中获取
			TbSeckillGoods seckillGoods = (TbSeckillGoods) redisTemplate.opsForValue().get("seckill_goods_" + seckillId);

			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
			if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
				System.out.println(seckillGoods.getStartTimeDate() + "==" + new Date());
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");


			}

			if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){

				LOGGER.info("活动结束时间 {}",seckillGoods.getEndTimeDate().getTime());
				LOGGER.info("现在时刻 {}",new Date().getTime());


				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}

			LOGGER.info("开始扣减库存 订单ID {}",seckillId);
			//扣减库存
			seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
			//销量加1
			seckillGoods.setSales(seckillGoods.getSales()+1);
			//更新秒杀信息
			seckillGoodsMapper.updateByPrimaryKey(seckillGoods);

			LOGGER.info("开始下单");

			//保存（redis）订单
			System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
			TbSeckillOrder seckillOrder=new TbSeckillOrder();
			seckillOrder.setId(orderId);
			seckillOrder.setCreateTime(new Date());
			//秒杀价格
			seckillOrder.setMoney(seckillGoods.getPrice());
			seckillOrder.setSeckillId(seckillId);
			//状态
			seckillOrder.setStatus("0");

			//保存订单
			seckillOrderMapper.insertSelective(seckillOrder);


		} catch (RuntimeException e) {
			e.printStackTrace();
		}
		return HttpResult.ok(orderId+"");
	}

	/**
	 * @Description: 4-1 使用队列的方式实现库存控制，以及性能提升
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Override
	public HttpResult startSubmitOrderByBockingQueue(Long seckillId, String userId) {

		try{
			Runnable task = () -> {
				//生成订单id,保证idworker是单例的状态，否则id冲突
				long orderId = idWorker.nextId();

				TbSeckillOrder order = new TbSeckillOrder();
				order.setId(orderId);
				//设置秒杀id
				order.setSeckillId(seckillId);
				//设置用户id
				order.setUserId(userId);

				//获取对象，把订单添加到队列中
				Boolean flag = null;
				try {
					flag = SeckillQueue.getMailQueue().produce(order);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				//通知用户下单成功，还是失败
				if(flag){
					LOGGER.info("用户队列方式下单：{} {}",order.getUserId(),"秒杀成功");
				}else {
					LOGGER.info("用户队列方式下单：{} {}",order.getUserId(),"秒杀失败");
				}

			};

			executor.execute(task);


		}catch (Exception e){
			e.printStackTrace();
		}

		return null;
	}
	


	/**
	 * @Description: 使用程序锁实现库存超卖控制
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrderByReentrantLock(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {

			//业务开始生活，加锁
			lock.lock();

			//xx.beginTransaction();

			LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
			// 1、 从数据库中查询商品信息 100线程
			TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillId);

			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
			if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");
			}

			if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}

			LOGGER.info("开始扣减库存 订单ID {}",seckillId);
			//扣减库存
			seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
			//销量加1
			seckillGoods.setSales(seckillGoods.getSales()+1);
			//更新秒杀信息
			seckillGoodsMapper.updateByPrimaryKey(seckillGoods);

			LOGGER.info("开始下单");

			//保存（redis）订单
			System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
			TbSeckillOrder seckillOrder=new TbSeckillOrder();
			seckillOrder.setId(orderId);
			seckillOrder.setCreateTime(new Date());
			//秒杀价格
			seckillOrder.setMoney(seckillGoods.getPrice());
			seckillOrder.setSeckillId(seckillId);
			//状态
			seckillOrder.setStatus("0");

			//保存订单
			seckillOrderMapper.insertSelective(seckillOrder);

			//xx.commit;

		} catch (RuntimeException e) {
			e.printStackTrace();
		}finally {
			//释放锁
			lock.unlock();
		}
		return HttpResult.ok(orderId+"");
	}


	/**
	 * @Description: 5-1 使用数据库悲观锁来进行库存控制
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrderBySQLLock(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {
			LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
			// 从数据库中查询商品信息 100线程
			TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKeyBySQLLock(seckillId);

			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
			if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");
			}

			if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}

			LOGGER.info("开始扣减库存 订单ID {}",seckillId);
			//扣减库存
			seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
			//销量加1
			seckillGoods.setSales(seckillGoods.getSales()+1);
			//更新秒杀信息
			seckillGoodsMapper.updateByPrimaryKey(seckillGoods);

			LOGGER.info("开始下单");

			//保存（redis）订单
			System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
			TbSeckillOrder seckillOrder=new TbSeckillOrder();
			seckillOrder.setId(orderId);
			seckillOrder.setCreateTime(new Date());
			//秒杀价格
			seckillOrder.setMoney(seckillGoods.getPrice());
			seckillOrder.setSeckillId(seckillId);
			//状态
			seckillOrder.setStatus("0");

			//保存订单
			seckillOrderMapper.insertSelective(seckillOrder);


		} catch (RuntimeException e) {
			e.printStackTrace();
		}

		return HttpResult.ok(orderId+"");
	}


	/**
	 * @Description: 5-2 使用数据库悲观锁来进行库存控制
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrderBySQLLock2(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {
			LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
			//商品数据可以从缓存中获取
			TbSeckillGoods seckillGoods = (TbSeckillGoods) redisTemplate.opsForValue().get("seckill_goods_" + seckillId);

			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
			if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");
			}

			if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}

			//更新秒杀信息
			seckillGoodsMapper.updateSeckillGoodsByPrimaryKeyByLock(seckillId);

			LOGGER.info("开始下单");

			//保存（redis）订单
			System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
			TbSeckillOrder seckillOrder=new TbSeckillOrder();
			seckillOrder.setId(orderId);
			seckillOrder.setCreateTime(new Date());
			//秒杀价格
			seckillOrder.setMoney(seckillGoods.getPrice());
			seckillOrder.setSeckillId(seckillId);
			//状态
			seckillOrder.setStatus("0");

			//保存订单
			seckillOrderMapper.insertSelective(seckillOrder);


		} catch (RuntimeException e) {
			e.printStackTrace();
		}

		return HttpResult.ok(orderId+"");
	}


	/**
	 * @Description: 5-3 使用数据库乐观锁进行库存控制
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrderBySQLLock3(Long seckillId, String userId) {
		long orderId = idWorker.nextId();
		try {
			LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
			//商品数据可以从缓存中获取
			TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillId);

			if(seckillGoods==null){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
			}
			if(1 != seckillGoods.getStatus()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
			}
			if(seckillGoods.getStockCount()<=0){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
			}
			if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");
			}

			if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){
				return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
			}

			//更新秒杀信息
			int i = seckillGoodsMapper.updateSeckillGoodsByPrimaryKeyByVersion(seckillId, seckillGoods.getVersion());

			//判断
			//乐观锁更新成功，后，才能开始下单
			if(i>0){

				LOGGER.info("开始下单");

				//保存（redis）订单
				System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
				TbSeckillOrder seckillOrder=new TbSeckillOrder();
				seckillOrder.setId(orderId);
				seckillOrder.setCreateTime(new Date());
				//秒杀价格
				seckillOrder.setMoney(seckillGoods.getPrice());
				seckillOrder.setSeckillId(seckillId);
				//状态
				seckillOrder.setStatus("0");

				//保存订单
				seckillOrderMapper.insertSelective(seckillOrder);
			}else{
				//返回
				return HttpResult.error("人太多了！请稍后重试");

			}

		} catch (RuntimeException e) {
			e.printStackTrace();
		}

		return HttpResult.ok(orderId+"");
	}




	/**
	 * @Description: 7-1 使用redisson分布式锁方案控制库存，实现下单
	 * @Author: hubin
	 * @CreateDate: 2020/9/5 20:48
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/9/5 20:48
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Transactional
	@Override
	public HttpResult startSubmitOrderByZookeeperLock(Long seckillId, String userId) {
		long orderId = idWorker.nextId();

		//加锁初始值
		try {

			//开始获取redis锁
			// 获取redis锁，尝试等待3s,上锁以后20s后锁自动解除
			// result = ZkLockUtil.acquire(3, TimeUnit.SECONDS);

			//判断获取锁是否成功
				LOGGER.info("开始下单条件校验 订单ID {}",seckillId);
				// 从数据库中查询商品信息 100线程
				//TbSeckillGoods seckillGoods = seckillGoodsMapper.selectByPrimaryKey(seckillId);

				//打印秒杀id
				LOGGER.info("-------------秒杀ID:{}",seckillId);

				//商品数据可以从缓存中获取
				TbSeckillGoods seckillGoods = (TbSeckillGoods) redisTemplate.opsForValue().get("seckill_goods_" + seckillId);

				//LOGGER.info("-------------秒杀对象属性ID,名称：{}",seckillGoods.getId());

				if(seckillGoods==null){
					return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品不存在");
				}
				if(1 != seckillGoods.getStatus()){
					return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品未审核");
				}
				if(seckillGoods.getStockCount()<=0){
					return HttpResult.error(HttpStatus.SC_NOT_FOUND,"商品已抢购一空");
				}
				if(seckillGoods.getStartTimeDate().getTime() > new Date().getTime()){
					return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动未开始");
				}

				if(seckillGoods.getEndTimeDate().getTime() <= new Date().getTime() ){
					return HttpResult.error(HttpStatus.SC_NOT_FOUND,"活动已结束");
				}

				LOGGER.info("开始扣减库存 订单ID {}",seckillId);
				/*//扣减库存
				seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
				//销量加1
				seckillGoods.setSales(seckillGoods.getSales()+1);
				//更新秒杀信息
				seckillGoodsMapper.updateByPrimaryKey(seckillGoods);*/

				//扣减redis库存
				//redis是内存版的数据库（AP模型），因此存在数据丢失的可能
				//工期
			//如果redis数据库永远不宕机，这个数据就是安全的
				//Long result = redisTemplate.opsForValue().increment("seckill_goods_stock_1", -1);
				Long result = redisTemplate.opsForValue().increment("seckill_goods_stock_" + seckillId, -1);
				// redis 和 MySQL数据一致性，通知mysql，库存发生了扣减
				//判断扣减库存是否成功
				if(result > 0){
					// 库存扣减成功
					LOGGER.info("库存扣减后结果:{}",result);
				}else if(result == 0){
					return HttpResult.ok("商品已售罄");
				}else{
					//扣减失败
					//库存进行回滚
					redisTemplate.opsForValue().increment("seckill_goods_stock_" + seckillId, 1);
					return HttpResult.error("秒杀失败");
				}

				LOGGER.info("开始下单");

				//保存（redis）订单
				System.out.println("cpu切换的随机性:======= "+ orderId +" ======");
				TbSeckillOrder seckillOrder=new TbSeckillOrder();
				seckillOrder.setId(orderId);
				seckillOrder.setCreateTime(new Date());
				//秒杀价格
				seckillOrder.setMoney(seckillGoods.getPrice());
				seckillOrder.setSeckillId(seckillId);
				//状态
				seckillOrder.setStatus("0");

				//保存订单
				seckillOrderMapper.insertSelective(seckillOrder);

		} catch (RuntimeException e) {
			e.printStackTrace();
		}/*finally {
			//必须要释放锁
			if(result){
				ZkLockUtil.release();
			}
		}*/

		//本地事务提交之后再发送消息
		/*TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
			@Override
			public void afterCommit(){
				//异步更新库存
				boolean result = mqSender.asyncReduceStock(seckillId + "");

			}
		});*/

	   return HttpResult.ok(orderId+"");
	}


	 /**
	  * @Description: 异步发送消息
	  * @Author: hubin
	  * @CreateDate: 2020/9/17 10:48
	  * @UpdateUser: hubin
	  * @UpdateDate: 2020/9/17 10:48
	  * @UpdateRemark: 修改内容
	  * @Version: 1.0
	  */
	 /*public void sendMessageTransaction(String seckillId,String userId){
		 //消息发送
		 if(!mqSender.transactionAsyncReduceStock(seckillId,userId)){
			 throw new RuntimeException("未知异常");
		 }
	 }*/

	/**
	 * @Description: 支付完毕，更新订单的状态
	 * @Author: hubin
	 * @CreateDate: 2020/6/10 22:20
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/6/10 22:20
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Override
	@Transactional
	public void updateOrderStatus(String out_trade_no, String transaction_id) {
		//1.修改支付日志状态

		TbPayLog payLog = payLogMapper.selectByPrimaryKey(out_trade_no);
		payLog.setPayTime(new Date());//支付时间
		payLog.setTradeState("1");//交易状态
		payLog.setTransactionId(transaction_id);//流水号
		payLogMapper.updateByPrimaryKey(payLog);

		//2.修改订单状态
		String orderList = payLog.getOrderList();
		String[] ids = orderList.split(",");//订单号
		for(String id:ids){

			TbSeckillOrder order = seckillOrderMapper.selectByPrimaryKey( Long.valueOf(id) );
			order.setStatus("2");//支付状态
			order.setPayTime(new Date());//支付时间
			seckillOrderMapper.updateByPrimaryKey(order);
		}
	}


	@Override
	public TbPayLog searchPayLogFromRedis(String userId) {
		return (TbPayLog) redisTemplate.boundHashOps("payLog").get(userId);
	}

	/**
	 * @Description: 根据token查询用户信息
	 * @Author: hubin
	 * @CreateDate: 2020/6/10 10:47
	 * @UpdateUser: hubin
	 * @UpdateDate: 2020/6/10 10:47
	 * @UpdateRemark: 修改内容
	 * @Version: 1.0
	 */
	@Override
	public FrontUser getUserInfoFromRedis(String token) {
		FrontUser user =
				(FrontUser) redisTemplate.opsForValue().get(token);
		return user;
	}

	@Override
	public HttpResult getOrderMoney(Long orderId) {
		TbSeckillOrder order = seckillOrderMapper.selectByPrimaryKey(orderId);
		HttpResult httpResult = new HttpResult();
		httpResult.setData(order.getMoney());
		return httpResult;
	}

	@Override
	public TbSeckillOrder findOrderById(Long orderId) {
		return seckillOrderMapper.selectByPrimaryKey(orderId);
	}
}
